import axios, { AxiosRequestConfig, AxiosResponse, CancelTokenSource } from 'axios';
import { ElMessage } from 'element-plus';
import { IGlobalState } from './global/types';
import { useCookie } from './hooks/useCookie';
import app from './main';

// 定义接口，用于指定请求返回值的数据结构
interface ResponseData {
    code: number;
    data: any;
    message: string;
}
// 封装 Axios
class HttpRequest {
    private baseUrl = process.env.VUE_APP_BASE_API + '/api';
    private source: CancelTokenSource;
    private static isAddOrDel = false;
    // 构造函数
    constructor() {
        axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
        axios.defaults.headers.patch['Content-Type'] = 'application/json;charset=utf-8';
        axios.defaults.baseURL = this.baseUrl;
        axios.defaults.timeout = 10000;
        this.source = axios.CancelToken.source();
    }

    // 请求拦截器
    private interceptors(config: AxiosRequestConfig) {
        config.cancelToken = this.source.token;
        const { method, url, data } = config;
        const global: IGlobalState = app.config.globalProperties.$global;
        const token = useCookie().getCookie(global.cookiesTokenName);

        if (token) {
            config.headers.Authorization = token;
        }
        // 在发送请求之前做些什么
        return config;
    }

    // 响应拦截器
    private interceptorsResponse(response: AxiosResponse<ResponseData>) {
        // 对响应数据做点什么
        const { status, data, config } = response;
        if (status !== 200) {
            // ElMessage.error('请求错误！');
            return Promise.reject('请求错误！');
        }
        return data;
    }

    // 封装请求
    public request(config: AxiosRequestConfig): Promise<any> {
        const instance = axios.create();
        instance.interceptors.request.use(this.interceptors.bind(this));
        instance.interceptors.response.use(this.interceptorsResponse.bind(this), (error) => {
            if (error && error.response) {
                switch (error.response.status) {
                    case 400:
                        error.message = '请求错误';
                        break;
                    case 401:
                        error.message = '未授权，请登录';
                        break;
                    case 402:
                        error.message = '未找到该用户'
                        break;
                    case 403:
                        error.message = '拒绝访问';
                        break;
                    case 404:
                        error.message = `请求地址出错: ${error.response.config.url}`;
                        break;
                    case 408:
                        error.message = '请求超时';
                        break;
                    case 500:
                        error.message = '服务器内部错误';
                        break;
                    case 501:
                        error.message = '服务未实现';
                        break;
                    case 502:
                        error.message = '网关错误';
                        break;
                    case 503:
                        error.message = '服务不可用';
                        break;
                    case 504:
                        error.message = '网关超时';
                        break;
                    case 505:
                        error.message = 'HTTP版本不受支持';
                        break;
                    default:
                }
            }
            error.response?.data && ElMessage.error(error.response.data) && console.error(error.response);
            return Promise.reject(error);
        });
        return instance(config);
    }
    // 封装取消请求
    public cancel(message?: string): void {
        this.source.cancel(message);
    }

    // 封装 GET 请求
    public get(url: string, data?: any): Promise<any> {
        const config: AxiosRequestConfig = {
            method: 'get',
            url,
            params: data
        };
        return this.request(config);
    }

    // 封装 POST 请求
    public post(url: string, data?: any): Promise<any> {
        const config: AxiosRequestConfig = {
            method: 'post',
            url,
            data
        };
        return this.request(config);
    }

    // 封装 PUT 请求
    public put(url: string, data?: any): Promise<any> {
        const config: AxiosRequestConfig = {
            method: 'put',
            url,
            data
        };
        return this.request(config);
    }

    // 封装 PATCH 请求
    public patch(url: string, data?: any): Promise<any> {
        const config: AxiosRequestConfig = {
            method: 'patch',
            url,
            data
        };
        return this.request(config);
    }

    // 封装 DELETE 请求
    public delete(url: string, data?: any): Promise<any> {
        const config: AxiosRequestConfig = {
            method: 'delete',
            url,
            params: data
        };
        return this.request(config);
    }
}

export default new HttpRequest();